package com.tuling.code.juc.lock;
/**
 * 双重检测锁 + 指令重排  (volatile的作用，保证指令重排)
 * volatile可以保证即使java虚拟机对代码执行了指令重排序，也会保证它的正确性
 * @see http://www.cnblogs.com/dolphin0520/p/3920373.html 
 * @author wangningbo
 *
 */
public class SingletonInstance {
	private volatile static SingletonInstance instance;  //加上volatile ，？？
	private SingletonInstance (){
		System.out.println("初始化");
	}
	
	/**
	 * 单例模式多线程安全问题，双重检测锁 + volitile 
	 * @return
	 */
	public static SingletonInstance getInstance(){
		if(null == instance){
			 // B线程检测到uniqueInstance不为空
			synchronized (SingletonInstance.class) {  //这样每次都加锁，有性能问题，在外面在进行一次判断
				if(null == instance){
					instance = new SingletonInstance();
					// A线程被指令重排了，刚好先赋值了；但还没执行完构造函数。假设构造函数有一堆东西在执行
				}
			}
		}
		return instance;  // 后面B线程执行时将引发：对象尚未初始化错误。所以为什么说还得加上volitile 才是最保险的
	}
	
	public static void main(String[] args) {
		for(int i =0;i<1000 ;i++){
			new Thread(new Runnable() {
				@Override
				public void run() {
					SingletonInstance.getInstance();
				}
			}).start();
		}
	}
}
